#ifndef BOOST__THREAD__UNILOCK_HPP
#  define BOOST__THREAD__UNILOCK_HPP

// Copyright (C) 2004-2009
// Alex Turbov, Igor Veresov
//
//  Distributed under the Boost Software License, Version 1.0. (See accompanying
//  file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)


#  include <boost/thread/details/unilock_interface_impl.hpp>
#  include <boost/thread/details/unilock_interface_wrapper.hpp>
#  include <boost/thread/default_scheduler.hpp>
#  include <boost/thread/parameterized_scheduler.hpp>
#  include <boost/thread/fifo_scheduler.hpp>

#  include <boost/mpl/integral_c.hpp>
#  include <boost/mpl/list_c.hpp>
#  include <boost/mpl/list.hpp>
#  include <boost/mpl/pair.hpp>

namespace boost {

/**
 * \brief This matrix (1x1 size) defines the only type of lock.
 *
 * \c unilock instantiated with this matrix (and default scheduler) becomes equivalent to mutex.
 *
 * \sa default_scheduler
 */
struct exclusive_lock
{
    enum type
    {
        lock
    };
    typedef mpl::list<
        mpl::pair<
            mpl::integral_c<type, lock>
          , mpl::list_c<bool, false>
          >
      > matrix_type;
};

/**
 * \brief This matrix defines read/write locking policy.
 */
struct rw_lock
{
    enum type
    {
        read
      , write
    };
    typedef mpl::list<                                      //      | Read | Write
        mpl::pair<                                          // -------------------
            mpl::integral_c<type, read>                     //      |      |
          , mpl::list_c<bool, true,  false>                 // Read |  1   | 0
          >                                                 //      |      |
      , mpl::pair<                                          //      |      |
            mpl::integral_c<type, write>                    //      |      |
          , mpl::list_c<bool, false, false>                 // Write|  0   | 0
          >                                                 //      |      |
      > matrix_type;
};

template <typename Scheduler>
class unilock
  : public mpl::apply<details::lock_interface_chooser, Scheduler, unilock<Scheduler> >::type
  , public mpl::apply<details::unlock_interface_chooser, Scheduler, unilock<Scheduler> >::type
{
public:
    typedef Scheduler scheduler_type;
    typedef BOOST_DEDUCED_TYPENAME scheduler_type::lock_params_type lock_params_type;
    typedef BOOST_DEDUCED_TYPENAME scheduler_type::unlock_params_type unlock_params_type;

private:
    typedef details::unilock_interface_impl<scheduler_type> impl_type;

    friend class mpl::apply<details::lock_interface_chooser, Scheduler, unilock<Scheduler> >::type;
    friend class mpl::apply<details::unlock_interface_chooser, Scheduler, unilock<Scheduler> >::type;

    impl_type m_impl;

    void do_lock(BOOST_DEDUCED_TYPENAME call_traits<lock_params_type>::param_type p)
    {
        m_impl.lock(p);
    }
    bool do_try_lock(BOOST_DEDUCED_TYPENAME call_traits<lock_params_type>::param_type p)
    {
        return m_impl.try_lock(p);
    }
    void do_unlock(BOOST_DEDUCED_TYPENAME call_traits<unlock_params_type>::param_type p)
    {
        m_impl.unlock(p);
    }
};

}
#endif                                                      // #ifndef BOOST__THREAD__UNILOCK_HPP
